import {
  useState,
  forwardRef,
  useRef,
  useEffect,
  useCallback,
  useImperativeHandle,
  useMemo,
} from 'react';
import { useIntl } from 'react-intl';
import { createPortal } from 'react-dom';
import { Button, Checkbox, List, Tabs } from 'antd-mobile';
import { AddOutline } from 'antd-mobile-icons';
import { useUpdateEffect } from 'ahooks';
import { useField } from '@formily/react';
import { getMessage, TextWidget } from '@inbiz/react';
import SimpleListView from '@inbiz/basic/SimpleListView';
import NavHeader from '@inbiz/basic/WapNavHeader';
import Breadcrumb from '@inbiz/basic/WapBreadcrumb';
import { InbizIcon, useEvents, getParents } from '@inbiz/utils';
import api from './api';
import Util, { IFileType, IFolderType } from './util';
import EformSelectFolderService, {
  getDocumentInfoByFile,
  getDocumentInfoByFolder,
} from './service';
// import styles from './index.less';
import './index.less';

export type ModeType = 'SelectFolder' | 'SelectFile';
const { Tab } = Tabs;
type IProps = {
  mode: ModeType;
  value: any[];
  inbiz: any;
  callBackEvents: any;
  showPersonalLibrary: boolean;
  onChange: (data: any) => void;
  className: string;
  originValue: any;
  storageConfig: any;
  childModelConfig: boolean;
  controlId: string;
  readOnly: boolean;
  // current: any;
  emit?: {
    /**首次渲染时触发*/
    (type: 'onload'): void;
    /**select事件*/
    (type: 'onSelect', data: any[], changeData?: any[]): void;
    /**值改变事件*/
    (type: 'onChange', data: any[]): void;
    /**打开弹框时执行*/
    (type: 'onOpen', data?: any[]): void;
    /**关闭弹框时执行*/
    (type: 'onClose', data: any[]): void;
    /**查看文件时执行*/
    (type: 'onFilePreview', fileid: string): void;
  };
  remoteServer?: {
    //第三方服务器， 用于文件摆渡
    url: string;
    token: string;
  };
  [key: string]: any;
};
const EformSelectFolder = (props: IProps, ref: any) => {
  const { mode, multiple, value, readOnly, showPersonalLibrary } = props;
  const intl = useIntl();
  const util = new Util({ intl });

  const [configEvents] = useEvents(props.callBackEvents, props.emit);

  const [visible, _visible] = useState(false);

  const setValue = useCallback(
    (value?: any) => {
      let old = value ? (Array.isArray(value) ? value : [value]) : [];
      props.onChange(old);
    },
    [multiple],
  );
  const deleteItem = useCallback(
    (data: IFileType | IFolderType) => () => {
      const newState = (props.value && [...props.value]) || [];
      const index = newState.findIndex(
        (item: any) => item.id == data.id && item.type === data.type,
      );
      if (index != -1) {
        newState.splice(index, 1);
      }
      props.onChange(newState);
    },
    [props.value],
  );
  useImperativeHandle(ref, () => api(configEvents, props), [props.value]);

  useEffect(() => {
    props.emit?.('onload');
  }, []);

  const renderList = useMemo(() => {
    if (props.value?.length) {
      return props.value.map((item) => (
        <div className="selectDocItem" key={item.id}>
          <img src={util.getRowIcon(item)} className="left" />
          <div className="center">
            <p className="ellipsis">{item.name}</p>
          </div>
          {!readOnly && (
            <div className="right" onClick={deleteItem(item)}>
              <InbizIcon
                type="icon-a-shanchulajitong"
                style={{ margin: '5px 8px 0 0', fontSize: 20, color: '#999' }}
              />
            </div>
          )}
        </div>
      ));
    } else {
      return undefined;
    }
  }, [readOnly, props.value]);

  const buttonClick = async () => {
    let result = (await configEvents.current?.onBeforeOpen?.('open')) ?? true;
    if (!result) {
      return;
    }

    if (!props.inbiz.browser.designer && !readOnly) {
      props.emit?.('onOpen', props.value);
      _visible(true);
    }
  };

  const onCancel = async () => {
    let result = (await configEvents.current?.onBeforeClose?.('open')) ?? true;

    if (!result) {
      return;
    }
    props.emit?.('onClose', props.value);
    _visible(false);
  };

  const onClose = async () => {
    let result = (await configEvents.current?.onBeforeClose?.('open')) ?? true;

    if (!result) {
      return;
    }
    props.emit?.('onClose', props.value);
    _visible(false);
  };
  const field = useField();

  const getLabelExtra = useCallback(() => {
    field.decoratorProps.labelExtra = () => (
      <div className="ant-formily-item-label-extra">
        <div style={{ width: 100, height: 1 }}></div>
        <div
          className="listButton"
          style={{
            color: readOnly ? '#ccc' : '',
            cursor: readOnly ? 'no-drop' : '',
          }}
          onClick={() => {
            buttonClick();
          }}
        >
          <AddOutline
            style={{ fontSize: 20, marginRight: '8px', verticalAlign: 'sub' }}
          />
          {props.placeholder}
        </div>
      </div>
    );
  }, [props.placeholder, field]);
  useEffect(() => {
    if (!field.decoratorProps.labelExtra) {
      getLabelExtra();
    }
  }, [field]);

  useUpdateEffect(() => {
    getLabelExtra();
  }, [props.placeholder]);

  return (
    <div
      className={`${'selectedMain'} ${props.className} ${'selectDoc'} ${props.mode
        }`}
    >
      {/* <div
        className="listButton"
        style={{ color: readOnly ? '#ccc' : '', cursor: readOnly ? 'no-drop' : '' }}
        onClick={() => {
          buttonClick();
        }}
      >
        <AddOutline style={{ fontSize: 20, marginRight: '8px', verticalAlign: 'sub' }} />
        {props.placeholder}
      </div> */}
      {renderList}
      <FolderSelectModal
        className={`${props.mode}Modal`}
        topFolder={props.topFolder}
        multiple={multiple}
        visible={visible}
        onCancel={() => {
          onCancel();
        }}
        onClose={() => {
          onClose();
        }}
        onOk={(selected) => {
          setValue(selected);
        }}
        util={util}
        mode={mode}
        emit={props.emit}
        showPersonalLibrary={showPersonalLibrary}
        selected={value || []}
        remoteServer={props.remoteServer}
      />
    </div>
  );
};

type FolderSelectModalProps = {
  multiple: boolean;
  visible: boolean;
  topFolder: any;
  onClose: () => Promise<boolean> | void;
  onCancel: () => Promise<boolean> | void;
  onOk: (selected: any[]) => void;
  util: any;
  mode: ModeType;
  selected: any[];
  emit: Function;
  showPersonalLibrary: boolean;
  className?: string;
  remoteServer?: {
    //第三方服务器， 用于文件摆渡
    url: string;
    token: string;
  };
};

type IFolderItem = {
  id: number;
  name: string;
  path?: string;
  namePath?: string;
  key?: string;
  pId?: number;
  type?: number;
};
const FolderSelectModal = forwardRef(function FolderSelectModal(
  props: FolderSelectModalProps,
  ref,
) {
  const { visible, onClose, onOk, util, mode, emit } = props;
  const intl = useIntl();
  const curTab = useRef<{ current: any }>();
  const service = new EformSelectFolderService({
    intl: intl,
    remoteServer: props.remoteServer,
  });
  const [tabs, _tabs] = useState<any[]>([]);
  const [activeTab, _activeTab] = useState(0);

  const [loading, _loading] = useState(false);

  // 保存所有选中的项
  const [selected, setSelected] = useState<IFolderItem[]>([]);
  useEffect(() => {
    setSelected(
      (props.selected || []).map((item) => {
        return { ...item, type: mode === 'SelectFile' ? 2 : 1 };
      }),
    );
  }, [props.selected, mode]);

  const onRightClick = useCallback(() => {
    onOk(selected);
    onClose();
  }, [selected]);

  const setLoading = (ing: boolean, pageNum: number, isRefresh?: boolean) => {
    if (pageNum == 1) {
      if (isRefresh) {
        _loading(false);
      } else {
        _loading(ing);
      }
    } else {
      _loading(false);
    }
  };

  const onLoadData = useCallback(
    (params?: { isRefresh: boolean }) => {
      setLoading(true, 1, params?.isRefresh);
      if (!params || !params?.isRefresh) {
        _tabs([]);
      }
      return service
        .getTopFolders({
          topFolderIds:
            props.topFolder?.length > 0 ? props.topFolder?.[0].id : 1,
          showEnterprise: true,
          showPerson: props.showPersonalLibrary,
          showTeam: false,
        })
        .then((res) => {
          if (Array.isArray(res)) {
            let newData = res.map((v: any) => {
              return util.formatData(v);
            });
            _tabs(newData);
          }
          setLoading(false, 1, params?.isRefresh);
        })
        .catch((e) => {
          setLoading(false, 1, params?.isRefresh);
        });
    },
    [props.topFolder, props.remoteServer],
  );

  useEffect(() => {
    if (props.visible) {
      onLoadData();
    } else {
      _tabs([]);
    }
  }, [visible, props.remoteServer]);

  useImperativeHandle(
    ref,
    () => {
      return {
        setActiveTab: (tabIndex: number) => {
          _activeTab(tabIndex);
        },
      };
    },
    [],
  );

  return visible && !!tabs?.length
    ? createPortal(
      <div className={`selectDocModel ${props.className || ''}`}>
        <NavHeader
          onLeftClick={() => {
            props.onCancel();
          }}
        />
        {
          <Tabs
            activeKey={activeTab.toString()}
            className={'tabs'}
            onChange={(key: string) => {
              _activeTab(Number(key));
            }}
          >
            {tabs.map((tab, index) => {
              return (
                <Tab title={tab.name} key={index.toString()} forceRender>
                  <TabItem
                    tab={tab}
                    multiple={props.multiple}
                    setSelected={setSelected}
                    selected={selected}
                    ref={curTab}
                    onOk={onRightClick}
                    util={util}
                    mode={mode}
                    emit={emit}
                    remoteServer={props.remoteServer}
                  />
                </Tab>
              );
            })}
          </Tabs>
        }
      </div>,
      document.body,
    )
    : null;
});

const TabItem = forwardRef(function (
  props: {
    tab: any;
    multiple: boolean;
    selected: any[];
    setSelected: React.Dispatch<React.SetStateAction<IFolderItem[]>>;
    onOk: () => void;
    util: any;
    mode: ModeType;
    emit: any;
    onChange: (data: any) => void;
    remoteServer?: {
      //第三方服务器， 用于文件摆渡
      url: string;
      token: string;
    };
  },
  ref: any,
) {
  const { mode, util, tab, multiple, selected, setSelected, onOk, emit } =
    props;

  const intl = useIntl();
  const service = new EformSelectFolderService({
    intl: intl,
    remoteServer: props.remoteServer,
  });
  const [bread, _bread] = useState<any[]>([
    {
      folderid: tab.id,
      folderName: tab.name,
    },
  ]);
  const [pageNum, _pageNum] = useState(1);
  const [pageSize, _pageSize] = useState(15);
  const [total, _total] = useState(0);
  const [data, _data] = useState<any[]>([]);
  const [refreshing, _refreshing] = useState(false);
  const [loading, _loading] = useState(false);
  const [loadingMore, _loadingMore] = useState(false);
  const [isSelectedAll, _isSelectedAll] = useState(false);
  let hasMore = pageNum <= Math.ceil(total / pageSize);
  let currentBread = bread[bread.length - 1];

  const setLoading = (ing: boolean, pageNum: number, isRefresh?: boolean) => {
    if (pageNum == 1) {
      _loadingMore(false);
      if (isRefresh) {
        _loading(false);
        _refreshing(ing);
      } else {
        _refreshing(false);
        _loading(ing);
      }
    } else {
      _refreshing(false);
      _loading(false);
      _loadingMore(ing);
    }
  };
  const onLoadChildData = useCallback(
    (params: {
      folderid: number;
      pageNum: number;
      pageSize: number;
      isRefresh?: boolean;
      isloadMore?: boolean;
    }) => {
      let pageNum = params.pageNum;
      setLoading(true, pageNum, params.isRefresh);
      if (pageNum == 1 && !params.isRefresh && !params.isloadMore) {
        _pageNum(1);
        _total(0);
        _data([]);
      }
      let promise =
        mode == 'SelectFolder'
          ? service.getFolderChilren({
            folderid: params.folderid,
            pageNum: params.pageNum,
            pageSize: params.pageSize,
          })
          : service.getFileAndFolderChildren({
            folderid: params.folderid,
            pageNum: params.pageNum,
            pageSize: params.pageSize,
          });
      return promise
        .then((res: any) => {
          let newData: any;
          let totalCount = 0;
          // 文件选择时res为数组，文件夹选择时res为对象
          if (Array.isArray(res)) {
            totalCount = res.pop();
            newData = res;
          } else if (Array.isArray(res?.children)) {
            totalCount = res.childrentotalcount;
            newData = res?.children;
          }
          if (newData) {
            // 过滤引用文件
            newData = newData.filter((item: any) => {
              return item.filetype != 32;
            });
            newData = newData.map((v: any) => {
              return util.formatData(v);
            });
            _data(params.pageNum > 1 ? [...data, ...newData] : newData);
          }
          _pageNum(params.pageNum);
          // _pageNum(params.pageSize);
          // _total(res.ChildrenTotalCount);
          _total(totalCount);
          setLoading(false, pageNum, params.isRefresh);
        })
        .catch((e) => {
          setLoading(false, pageNum, params.isRefresh);
        });
    },
    [data, mode],
  );

  const onRefresh = useCallback(() => {
    onLoadChildData({
      folderid: currentBread.folderid,
      pageNum: 1,
      pageSize: pageSize,
      isRefresh: true,
    });
  }, [currentBread, pageSize]);

  const onLoadMore = useCallback(() => {
    if (loadingMore || !hasMore) return;
    if (currentBread) {
      onLoadChildData({
        pageNum: pageNum + 1,
        pageSize: pageSize,
        folderid: currentBread.folderid,
        isloadMore: true,
      });
    } else {
      return;
    }
  }, [currentBread, pageNum, pageSize, loadingMore, hasMore]);
  const onClickRow = useCallback(
    (row, _index, e) => {
      if (e) {
        let checkbox = e.currentTarget.querySelector('.adm-checkbox');
        let parents = [];
        if (checkbox) {
          parents = getParents(e.target, checkbox);
        }
        if (checkbox && e.target === checkbox) {
          return;
        }
        if (!parents.length) {
          if (row.type == 1) {
            _pageNum(1);
            _total(0);
            _data([]);
            _bread((bread) => [
              ...bread,
              {
                folderid: row.id,
                folderName: row.name,
              },
            ]);
            onLoadChildData({
              folderid: row.id,
              pageNum: 1,
              pageSize: pageSize,
            });
          }
        }
      }
    },
    [bread, pageSize],
  );

  const onCheckboxChange = useCallback(
    (checked: boolean, row: any) => {
      if (multiple) {
        if (checked) {
          props.emit?.('onSelect', row);
          setSelected((selected) => [...selected, row]);
        } else {
          props.emit?.('onSelect', row);
          setSelected((selected) => [
            ...selected.filter((v) => v.id != row.id),
          ]);
        }
      } else {
        props.emit?.('onSelect', row);
        setSelected(checked ? [row] : []);
      }
    },
    [multiple, selected],
  );

  const selectData = useMemo(() => {
    return selected.reduce((pre, next) => {
      pre[next.id] = true;
      return pre;
    }, {});
  }, [selected]);
  const renderRow = useCallback(
    (row: any, index: number) => {
      return (
        <List.Item
          onClick={(e) => onClickRow(row, index, e)}
          className={'folderRow'}
          prefix={<img src={util.getRowIcon(row)} />}
          arrow={false}
          title={row.name}
          description={
            row.type == 1 ? (
              <div className="ellipsis">
                {row.childfilescount || 0}
                <TextWidget>EformSelectDoc.singleFile</TextWidget>{' '}
                {row.childfolderscount || 0}
                <TextWidget>EformSelectDoc.singleFolder</TextWidget>{' '}
                {util.getDateInterval(row.createtime)}
              </div>
            ) : (
              <p className="ellipsis">
                {row.version} {row.operator} {util.formatFileSize(row.size)}{' '}
                {util.getDateInterval(row.createtime)}
              </p>
            )
          }
          extra={
            mode == 'SelectFile' && row.type == 1 ? null : (
              <Checkbox
                checked={!!selectData[row.id]}
                style={
                  !!selectData[row.id] ? { transform: 'translateY(3px)' } : {}
                }
                onChange={(checked: boolean) => onCheckboxChange(checked, row)}
                icon={(checked) => {
                  if (checked) {
                    return (
                      <InbizIcon
                        type={'icon-success'}
                        style={{
                          fontSize: 16,
                          color: 'var(--inbiz-color-primary)',
                        }}
                      />
                    );
                  } else {
                    return <div className="adm-checkbox-icon"></div>;
                  }
                }}
              />
            )
          }
          key={`${row.type}:${row.id}`}
        />
      );
    },
    [selectData],
  );
  const onHome = () => { };
  const onBreadItemClick = useCallback(
    (e, item) => {
      for (let i = 0; i < bread.length; i++) {
        if (bread[i].folderid == item.folderid) {
          let newBread = bread.slice(0, i + 1);
          _bread(newBread);
          onLoadChildData({
            folderid: item.folderid,
            pageNum: 1,
            pageSize: pageSize,
          });
          break;
        }
      }
    },
    [bread, pageSize],
  );

  const onToggleSelectAll = useCallback(() => {
    if (!isSelectedAll) {
      let appendData: any[] = [];
      let list = data;
      if (mode === 'SelectFile') {
        list = list.filter((item) => item.type === 2);
      }
      list.forEach((row) => {
        if (!selectData[row.id]) {
          appendData.push(row);
        }
      });
      setSelected((selected) => {
        const newList = [...selected, ...appendData];
        return newList;
      });
    } else {
      setSelected([]);
    }
  }, [isSelectedAll, data, selected, selectData, mode]);

  useEffect(() => {
    let list = data;
    if (mode === 'SelectFile') {
      list = list.filter((item) => item.type == 2);
    }
    _isSelectedAll(
      list.length
        ? list.every((v) => {
          return selectData[v.id];
        })
        : false,
    );
  }, [data, selectData, mode]);

  useEffect(() => {
    onLoadChildData({
      folderid: tab.id,
      pageNum: 1,
      pageSize: pageSize,
    });
  }, [tab]);

  // useImperativeHandle(
  //   ref,
  //   () => {
  //     return {
  //       selectAll: () => {
  //         alert();
  //       },
  //       unSelectAll: () => {
  //         alert();
  //       },
  //     };
  //   },
  //   [selectData],
  // );
  return (
    <div className={'tabsItem'}>
      <Breadcrumb
        showHome={false}
        onClickHome={onHome}
        onBreadItemClick={onBreadItemClick}
        data={bread}
      />
      <SimpleListView
        onRefresh={onRefresh}
        dataSource={data}
        renderRow={renderRow}
        refreshing={refreshing}
        loading={loading}
        hasMore={hasMore}
        loadingMore={loadingMore}
        loadMore={onLoadMore}
        style={{
          flex: 1,
          overflow: 'auto',
          height: 'auto',
        }}
      />
      <div className={'selectedCountRow'}>
        <div className={'selectedCountRowLeft'}>
          {multiple ? (
            <span
              className={'selectAll'}
              onClick={(e) => {
                onToggleSelectAll();
              }}
            >
              {isSelectedAll
                ? getMessage('EformSelectDoc.cancelSelect')
                : getMessage('EformSelectDoc.selectAll')}
            </span>
          ) : null}
          <span className={'selected'}>
            <TextWidget>EformSelectDoc.selected</TextWidget>
            {selected.length}
            <TextWidget>EformSelectDoc.item</TextWidget>
          </span>
        </div>
        <Button
          color="primary"
          size="small"
          onClick={(e) => {
            onOk();
          }}
        >
          <TextWidget>EformSelectDoc.Ok</TextWidget>
        </Button>
      </div>
    </div>
  );
});
TabItem.displayName = 'TabItem';
EformSelectFolder.originValueFormat = (value: string, props: IProps) => {
  let mode = props.inbiz(props.controlId).__componentname;
  if (mode.includes?.('SelectFile$')) {
    return getDocumentInfoByFile(value, props).then((res) => {
      return (
        res?.map((item: any) => {
          return {
            ...item,
            // fileid: item.fileid,
            key: `${item.filetype}-${item.fileid}`,
            id:
              item.filetype == 1 || item.filetype === 0
                ? item.folderid
                : item.filetype == 2
                  ? item.fileid
                  : -1,
            name: item.filename,
            type: item.filetype,
          };
        }) || []
      );
    });
  } else {
    return getDocumentInfoByFolder(value, props).then((res) => {
      return res?.map((item: any, index: number) => {
        return {
          ...item,
          // folderid: item.folderid,
          key: `${item.foldertype}-${item.folderid}`,
          id:
            item.foldertype == 1 || item.foldertype === 0
              ? item.folderid
              : item.foldertype == 2
                ? item.fileid
                : -1,
          name: item.foldername,
          type: item.foldertype,
        };
      });
    });
  }
};

export default EformSelectFolder;
export type { IProps };
